package pipe;

import java.io.*;

//Generators fill output pipe with ints from first to last
class Generator extends Thread {

private DataOutputStream dout;
private int first, last;

public Generator(PipedOutputStream out, int start, int end) {
   // filter pipes into data streams
   dout = new DataOutputStream(out);
   first = start;
   last = end;
}

public void run() {

   for(int i = first; i <= last; i++) {
      try {
    	  System.out.println(i);
         dout.writeInt(i);
         sleep(5); // don't be selfish
      }
      catch(IOException e) {}
      catch(InterruptedException e){}
   }
}

} // Generator

//Accumulators sum all ints in input pipe
class Accumulator extends Thread {

private DataInputStream din;
private int accum = 0;

public Accumulator(PipedInputStream in) {
   // filter pipes into data streams
   din = new DataInputStream(in);
}

public void run() {

   boolean done = false;

   while(!done) {
      try {
    	  System.out.println(accum);
         accum += din.readInt();
         sleep(5);
      }
      catch(IOException e) { done = true; }
      catch(InterruptedException e) {}
   }

   System.out.println("Result = " + accum); // for now
}
} // Accumulator

//Filters put even ints from input stream into
//output stream (i.e. they filter out odds)
class Filter extends Thread {

private DataInputStream din;
private DataOutputStream dout;
private int next;

public Filter(PipedInputStream in, PipedOutputStream out) {
   // filter pipes into data streams
   din = new DataInputStream(in);
   dout = new DataOutputStream(out);
}

public void run() {

   boolean done = false;

   while(!done) {
      try {
         next = din.readInt();
         System.out.println("Filter "+next);
//         if (next % 2 == 0)
            dout.writeInt(next);
         sleep(5);
      }
      catch(IOException e) { done = true; }
      catch(InterruptedException e) {}
   }
}
} // Filter

//Amplifiers put squares of ints from input stream
//into output stream
class Amplifier extends Thread {

private DataInputStream din;
private DataOutputStream dout;
private int next;

public Amplifier(PipedInputStream in, PipedOutputStream out) {
   din = new DataInputStream(in);
   dout = new DataOutputStream(out);
}

public void run() {

   boolean done = false;

   while(!done) {
      try {
         next = din.readInt();
         System.out.println("Amplifier "+next);
         dout.writeInt(next * next);
         sleep(5);
      }
      catch(IOException e) { done = true; }
      catch(InterruptedException e) {}
   }
}
} // Amplifier

//computes sum of even squares of ints from 1 to 100
//= 2^2 + 4^2 + ... + 98^2 + 100^2
public class SumOfEvenSquares {

public static void main(String args[]) {

   try {

      // make some pipes
      PipedOutputStream pipe1 = new PipedOutputStream();
      PipedInputStream pipe2 = new PipedInputStream(pipe1);
      //try { pipe1.connect(pipe2); } catch(IOException e) {}
      PipedOutputStream pipe3 = new PipedOutputStream();
      PipedInputStream pipe4 = new PipedInputStream(pipe3);
      //try { pipe3.connect(pipe4); } catch(IOException e) {}
      PipedOutputStream pipe5 = new PipedOutputStream();
      PipedInputStream pipe6 = new PipedInputStream(pipe5);
      //try { pipe5.connect(pipe6); } catch(IOException e) {}

      // make some threads
      Generator g = new Generator(pipe1, 1, 10);
      Filter f = new Filter(pipe2, pipe3);
      Amplifier a = new Amplifier(pipe4, pipe5);
      Accumulator ac = new Accumulator(pipe6);

      // start threads
      g.start();
      f.start();
      a.start();
      ac.start();

      // close pipes
      pipe1.close();
      pipe2.close();
      pipe3.close();
      pipe4.close();
      pipe5.close();
      pipe6.close();
  }
  catch(IOException e) {}
}
} // SumOfEvenSquares 